<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>构造函数中的引用</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="oop4.magic-functions.html">魔术函数 __sleep 和 __wakeup</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="oop4.object-comparison.html">对象的比较</a></div>
 <div class="up"><a href="oop4.html">类与对象（PHP 4）</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="oop4.newref" class="sect1">
   <h2 class="title">构造函数中的引用</h2>
   <p class="para">
    在构造函数中创建引用可能会导致混淆的结果。本节以教程形式帮助避免问题。

    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">Foo&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;在全局数组&nbsp;$globalref&nbsp;中建立一个引用<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">global&nbsp;</span><span style="color: #0000BB">$globalref</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[]&nbsp;=&nbsp;&amp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;将名字设定为传递的值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;并输出之<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"&lt;br&nbsp;/&gt;"</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">name</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">name&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$name</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>
  </p>

  <p class="para">
   下面来检查一下用拷贝运算符 <em>=</em> 创建的 <var class="varname"><var class="varname">$bar1</var></var>
   和用引用运算符 <em>=&amp;</em> 创建的 <var class="varname"><var class="varname">$bar2</var></var>
   有没有区别...
   <div class="informalexample">
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />$bar1&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #DD0000">'set&nbsp;in&nbsp;constructor'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/*&nbsp;输出：<br />set&nbsp;in&nbsp;constructor<br />set&nbsp;in&nbsp;constructor<br />set&nbsp;in&nbsp;constructor&nbsp;*/<br /><br /></span><span style="color: #0000BB">$bar2&nbsp;</span><span style="color: #007700">=&amp;&nbsp;new&nbsp;</span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #DD0000">'set&nbsp;in&nbsp;constructor'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/*&nbsp;输出：<br />set&nbsp;in&nbsp;constructor<br />set&nbsp;in&nbsp;constructor<br />set&nbsp;in&nbsp;constructor&nbsp;*/<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>
  </p>
  <p class="para">
   显然没有区别，但实际上有一个非常重要的区别：<var class="varname"><var class="varname">$bar1</var></var>
   和 <var class="varname"><var class="varname">$globalref[0]</var></var>
   并没有被引用，它们不是同一个变量。这是因为“new”默认并不返回引用，而返回一个拷贝。
   <blockquote class="note"><p><strong class="note">Note</strong>: 
    <span class="simpara">
     在返回拷贝而不是引用中并没有性能上的损失（因为
     PHP 4 及以上版本使用了引用计数）。相反更多情况下工作于拷贝而不是引用上更好，因为建立引用需要一些时间而建立拷贝实际上不花时间（除非它们都不是大的数组或对象，而其中之一跟着另一个变，那使用引用来同时修改它们会更聪明一些）。
    </span>
   </p></blockquote>
   要证明以上写的，看看下面的代码。
   <div class="informalexample">
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">//&nbsp;现在改个名字，你预期什么结果？<br />//&nbsp;你可能预期&nbsp;$bar1&nbsp;和&nbsp;$globalref[0]&nbsp;二者的名字都改了...<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #DD0000">'set&nbsp;from&nbsp;outside'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;但如同前面说的，并不是这样。<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/*&nbsp;输出为：<br />set&nbsp;from&nbsp;outside<br />set&nbsp;in&nbsp;constructor&nbsp;*/<br /><br />//&nbsp;现在看看&nbsp;$bar2&nbsp;和&nbsp;$globalref[1]&nbsp;有没有区别<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #DD0000">'set&nbsp;from&nbsp;outside'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;幸运的是它们不但相同，根本就是同一个变量。<br />//&nbsp;因此&nbsp;$bar2-&gt;name&nbsp;和&nbsp;$globalref[1]-&gt;name&nbsp;也是同一个变量。<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]-&gt;</span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/*&nbsp;输出为：<br />set&nbsp;from&nbsp;outside<br />set&nbsp;from&nbsp;outside&nbsp;*/<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

   </div>
  </p>
  <p class="para">
   最后给出另一个例子，试着理解它。

   <div class="informalexample">
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">A&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">A</span><span style="color: #007700">(</span><span style="color: #0000BB">$i</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$i</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">//&nbsp;试着想明白为什么这里不需要引用<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">b&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">B</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">createRef</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">c&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">B</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"&lt;br&nbsp;/&gt;"</span><span style="color: #007700">,</span><span style="color: #DD0000">"class&nbsp;"</span><span style="color: #007700">,</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">),</span><span style="color: #DD0000">':&nbsp;'</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /><br />class&nbsp;</span><span style="color: #0000BB">B&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">B</span><span style="color: #007700">(&amp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a&nbsp;</span><span style="color: #007700">=&nbsp;&amp;</span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #DD0000">"&lt;br&nbsp;/&gt;"</span><span style="color: #007700">,</span><span style="color: #DD0000">"class&nbsp;"</span><span style="color: #007700">,</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">),</span><span style="color: #DD0000">':&nbsp;'</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;试着理解为什么这里一个简单的拷贝会在下面用&nbsp;*<br />//&nbsp;标出来的行中产生预期之外的结果<br /></span><span style="color: #0000BB">$a&nbsp;</span><span style="color: #007700">=&amp;&nbsp;new&nbsp;</span><span style="color: #0000BB">A</span><span style="color: #007700">(</span><span style="color: #0000BB">10</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">createRef</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">b</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">c</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">11</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">b</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();&nbsp;</span><span style="color: #FF8000">//&nbsp;*<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">c</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
    </div>

    <p class="para">以上例程会输出：</p>
    <div class="example-contents screen">
<div class="cdata"><pre>
class A: 10
class B: 10
class B: 10
class A: 11
class B: 11
class B: 11
</pre></div>
    </div>
   </div>
  </p>
 </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="oop4.magic-functions.html">魔术函数 __sleep 和 __wakeup</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="oop4.object-comparison.html">对象的比较</a></div>
 <div class="up"><a href="oop4.html">类与对象（PHP 4）</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>
